#ifndef _XX_YY_BMOCK_ARG_LIST
#define _XX_YY_BMOCK_ARG_LIST

#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include "bmock_argument.hpp"

namespace bmock {
	struct arg_list : private std::pair<const argument *,const argument *> {
		arg_list(const argument *const args,size_t count)
			:std::pair<const argument *,const argument *>(args,args+count)
		{}
		size_t size() const;
		bool   is_empty() const;
		void   print(std::ostream &) const;

		template<typename Iterator>
		bool args_differ(const arg_checker &chk,Iterator arg_vals) const {
			return comp_args(chk,arg_vals,&argument::validate);
		}
		template<typename Iterator>
		bool args_differ_no_msg(const arg_checker& chk, Iterator arg_vals) const {
			return comp_args(chk, arg_vals, &argument::validate_no_msg);
		}
		template<typename Iterator>
		bool update_failed(const arg_checker &chk,Iterator arg_vals) const {
			return comp_args(chk,arg_vals,&argument::update);
		}
		template<typename Iterator>
		void save(const arg_checker &chk,Iterator arg_vals) const {
			std::transform(first,second,arg_vals,boost::lambda::bind(&argument::get_value,boost::lambda::_1,boost::cref(chk)));
		}
	private:
		template<typename Iterator,typename ArgMethod>
		bool comp_args(const arg_checker &chk,Iterator arg_vals,ArgMethod m) const {
			return !std::equal(std::pair<const argument *,const argument *>::first,std::pair<const argument *,const argument *>::second,arg_vals,!boost::lambda::bind(m,boost::lambda::_1,boost::cref(chk),boost::lambda::_2));
		}
	};
}

namespace std {
	std::ostream &operator <<(std::ostream &,const bmock::arg_list &);
}

#include <boost/preprocessor/list/for_each.hpp>
#include <boost/preprocessor/tuple/to_list.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp> 
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>

#include "bmock_expand_arg.hpp"

#define __BMOCK_REAL_ARG_LIST(N,IAL)\
	const bmock::argument args_[] = {\
	__BMOCK_EXPAND_ARG_LIST(N,IAL)\
				}; 

#define __BMOCK_EMPTY_ARG_LIST(N,IAL)\
	const bmock::argument *args_ = 0; 

#define __BMOCK_ARG_LIST(N,IAL)\
	BOOST_PP_EXPAND(\
	BOOST_PP_IF(N,__BMOCK_REAL_ARG_LIST,__BMOCK_EMPTY_ARG_LIST)\
	)(N,IAL)

#endif
